#include "ImageBitmap.h"
#include "Drawer.h"

#include <unordered_set>
#include <deque>

namespace HW2
{

	ImageBitmap::ImageBitmap() :  minPoint(1<<30, 1<<30), maxPoint(-(1<<30),-(1<<30))
	{
	}

	void ImageBitmap::set(Point2D &p)
	{
		pixels.push_back(p);
	}
	bool ImageBitmap::operator<(ImageBitmap& I)
	{
		return z < I.z;
	}

	bool ImageBitmap::inside(Point2D point)
	{
		if(point < minPoint ||point > maxPoint) 
			return false;

		unsigned int i, j;
		bool inside = 0;
		// int pnpoly(int nvert, float *vertx, float *verty, float testx, float testy)
		for (i = 0, j = points.size()-1; i < points.size(); j = i++) {
			if ( ((points[i].y>point.y) != (points[j].y>point.y)) &&
				(point.x < (points[j].x-points[i].x) * (point.y-points[i].y) / (points[j].y-points[i].y) + points[i].x) )
				inside = !inside;
		}
		return inside;
	}

	void ImageBitmap::draw()
	{
		Drawer &d = Drawer::get();
		
		if(p->filled)
			drawFill();
		d.setColor(p->color);

		for(unsigned int i= 0; i < pixels.size(); i++)
		{
			d.plot(pixels[i].x, pixels[i].y);
		}
	}

	void ImageBitmap::drawFill()
	{

		// TODO: fill a polygon
		// we have a box: upper left corner is minPoint, lower right is maxPoint
		// Inside, we have a polygon, whose pixels are stored in the "pixels" std::vector
		// fill it! for now, as a workaround, I just set the color of the polygon to green.

		/* TO REMOVE */ Drawer::get().setColor(Color(0,255,0)); /* TO REMOVE */
		std::unordered_set<Point2D> pixelset, pointset;
		for(int i= 0; i < pixels.size(); i++)
		{
			pixelset.insert(pixels[i]);
		}
		
		int x = minPoint.x;
		int y = minPoint.y;
		while(pixelset.find(Point2D(x,y)) == pixelset.end())
			x++;
		while(pixelset.find(Point2D(x,y)) != pixelset.end())
			y++;

		std::deque<Point2D> q;
		q.push_back(Point2D(x,y));

		while(!q.empty())
		{
			int x = q.front().x;
			int y = q.front().y;
			q.pop_front();
			if(pixelset.find(Point2D(x,y)) != pixelset.end())
				continue;
			if(x < minPoint.x || x > maxPoint.x || y < minPoint.y || y > maxPoint.y)
				continue;
			pixelset.insert(Point2D(x,y));
			Drawer::get().plot(x,y);
			q.push_back(Point2D(x+1,y));
			q.push_back(Point2D(x-1,y));
			q.push_back(Point2D(x,y+1));
			q.push_back(Point2D(x,y-1));
		}
	}

	void ImageBitmap::plot(int x, int y, double z, Color c, Coordinates orig)
	{
		set(Point2D(x,y));
	}

}